/*  Army Editor for yALB - Yet Another List Builder (roster Editor for Wargames/tabletop games).
    Copyright (C) 2008-2012  Daniel Ricardo Castro Alvarado

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.*/

#include "armyeditor.h"
#include "ui_armyeditor.h"

#include "other/structreader.h"
#include "other/structwriter.h"
#include "startdialog.h"
#include "other/categorizermodel.h"

#include "other/optionmodel.h"
#include "other/itemmodel.h"
#include "other/categorymodel.h"

#include <QMessageBox>
#include <QHash>
#include <QFileDialog>
#include <QDesktopWidget>
#include <QDebug>
#include <QTimer>
#include <QLibraryInfo>

// TODO: Use model-based views instead of item-based widgets

// \TODO: How should I manage game and army categories with models? It would be good to allow "overwrite" complete categories of the game with the ones of army,
// probably the best for this case is work with two models and have one that mix them.
// Accepted solution: Use two collections with two models, and merge them in another one.

ArmyEditor::ArmyEditor(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::ArmyEditor)
{
    ui->setupUi(this);
    setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, size(), QDesktopWidget().availableGeometry()));

    armyModels.unitCategoryModel = new CategoryModel(&armyData.unitCategories, this);
    armyModels.itemCategoryModel = new CategoryModel(&armyData.itemCategories, this);
    armyModels.optionCategoryModel = new CategoryModel(&armyData.optionCategories, this);
    armyModels.itemModel = new ItemModel(&armyData.items, this);
    armyModels.optionModel = new OptionModel(&armyData.options, this);

    gameModels.unitCategoryModel = new CategoryModel(&gameData.unitCategories, this);
    gameModels.itemCategoryModel = new CategoryModel(&gameData.itemCategories, this);
    gameModels.optionCategoryModel = new CategoryModel(&gameData.optionCategories, this);
    gameModels.itemModel = new ItemModel(&gameData.items, this);
    gameModels.optionModel = new OptionModel(&gameData.options, this);

    dualUnitCategoryModel = new DualModel(gameModels.unitCategoryModel, armyModels.unitCategoryModel, this);
    dualItemCategoryModel = new DualModel(gameModels.itemCategoryModel, armyModels.itemCategoryModel, this);
    dualOptionCategoryModel = new DualModel(gameModels.optionCategoryModel, armyModels.optionCategoryModel, this);


    itemCategorizerModel = new CategorizerModel(dualItemCategoryModel, armyModels.itemModel,this);
    optionCategorizerModel = new CategorizerModel(dualOptionCategoryModel, armyModels.optionModel, this);

    // \FIXME: Only uses army data
    itemSelector = new ItemSelector(armyData.items, gameData.itemCategories);

    unitCategoryWidget = new CategoryWidget(&armyData.unitCategories, armyModels.unitCategoryModel);
    itemCategoryWidget = new CategoryWidget(&armyData.itemCategories, armyModels.itemCategoryModel);
    optionCategoryWidget = new CategoryWidget(&armyData.optionCategories, armyModels.optionCategoryModel);
    ui->tabUnitCategories->layout()->addWidget(unitCategoryWidget);
    ui->tabItemCategories->layout()->addWidget(itemCategoryWidget);
    ui->tabOptionCategories->layout()->addWidget(optionCategoryWidget);

    ui->listView->setModel(armyModels.itemModel);

    categoryDialog = new CategoryLimitDialog(this);

    optionWidget = new OptionWidget(&armyData.options, optionCategorizerModel, *itemSelector, this);
    ui->tabOptions->layout()->addWidget(optionWidget);

    itemWidget = new ItemWidget(&armyData.items, itemCategorizerModel, *itemSelector, this);
    ui->tabItems->layout()->addWidget(itemWidget);

    unitWidget = new UnitWidget(armyData.units, *itemSelector, *categoryDialog);
    ui->tabUnits->layout()->addWidget(unitWidget);

    textWidget = new GlobalTextWidget(&armyData.globalTexts);
    ui->tabTexts->layout()->addWidget(textWidget);

    // \FIXME: Commented

    /*connect(&optionCategories, SIGNAL(categoryAdded(GameCategory,QString)),
            optionWidget, SLOT(addCategory(GameCategory,QString)));
    connect(&optionCategories, SIGNAL(categoryUpdated(QString,GameCategory,QString)),
            optionWidget, SLOT(updateCategory(QString,GameCategory,QString)));
    connect(&optionCategories, SIGNAL(categoryRemoved(QString)),
            optionWidget, SLOT(removeCategory(QString)));

    connect(&optionCategories, SIGNAL(categoryAdded(GameCategory,QString)),
            unitWidget, SLOT(addOptionCategory(GameCategory,QString)));
    connect(&optionCategories, SIGNAL(categoryUpdated(QString,GameCategory,QString)),
            unitWidget, SLOT(updateOptionCategory(QString,GameCategory,QString)));
    connect(&optionCategories, SIGNAL(categoryRemoved(QString)),
            unitWidget, SLOT(removeOptionCategory(QString)));

    connect(&unitCategories, SIGNAL(categoryAdded(GameCategory,QString)),
            unitWidget, SLOT(addUnitCategory(GameCategory,QString)));
    connect(&unitCategories, SIGNAL(categoryUpdated(QString,GameCategory,QString)),
            unitWidget, SLOT(updateUnitCategory(QString,GameCategory,QString)));
    connect(&unitCategories, SIGNAL(categoryRemoved(QString)),
            unitWidget, SLOT(removeUnitCategory(QString)));

    connect(&itemCategories, SIGNAL(categoryAdded(GameCategory,QString)),
            itemWidget, SLOT(addCategory(GameCategory,QString)));
    connect(&itemCategories, SIGNAL(categoryUpdated(QString,GameCategory,QString)),
            itemWidget, SLOT(updateCategory(QString,GameCategory,QString)));
    connect(&itemCategories, SIGNAL(categoryRemoved(QString)),
            itemWidget, SLOT(removeCategory(QString)));

    connect(&itemCategories, SIGNAL(categoryAdded(GameCategory,QString)),
            categoryDialog, SLOT(addCategory(GameCategory,QString)));
    connect(&itemCategories, SIGNAL(categoryUpdated(QString,GameCategory,QString)),
            categoryDialog, SLOT(updateCategory(QString,GameCategory,QString)));
    connect(&itemCategories, SIGNAL(categoryRemoved(QString)),
            categoryDialog, SLOT(removeCategory(QString)));

    connect(&itemCategories, SIGNAL(cleared()), categoryDialog, SLOT(clearAll()));*/

    // Game file related signals set up

    // \FIXME: Commented..

    /*connect(gameFileData.optionProperties, SIGNAL(propertyAdded(GameProperty,QString)),
            optionWidget, SLOT(addProperty(GameProperty,QString)));
    connect(gameFileData.optionProperties, SIGNAL(propertyUpdated(QString,GameProperty,QString)),
            optionWidget, SLOT(updateProperty(QString,GameProperty,QString)));
    connect(gameFileData.optionProperties, SIGNAL(propertyRemoved(QString)),
            optionWidget, SLOT(removeProperty(QString)));

    connect(gameFileData.itemProperties, SIGNAL(propertyAdded(GameProperty,QString)),
            itemWidget, SLOT(addProperty(GameProperty,QString)));
    connect(gameFileData.itemProperties, SIGNAL(propertyUpdated(QString,GameProperty,QString)),
            itemWidget, SLOT(updateProperty(QString,GameProperty,QString)));
    connect(gameFileData.itemProperties, SIGNAL(propertyRemoved(QString)),
            itemWidget, SLOT(removeProperty(QString)));

    connect(gameFileData.optionProperties, SIGNAL(propertyAdded(GameProperty,QString)),
            unitWidget, SLOT(addOptionProperty(GameProperty,QString)));
    connect(gameFileData.optionProperties, SIGNAL(propertyUpdated(QString,GameProperty,QString)),
            unitWidget, SLOT(updateOptionProperty(QString,GameProperty,QString)));
    connect(gameFileData.optionProperties, SIGNAL(propertyRemoved(QString)),
            unitWidget, SLOT(removeOptionProperty(QString)));

    connect(gameFileData.unitProperties, SIGNAL(propertyAdded(GameProperty,QString)),
            unitWidget, SLOT(addUnitProperty(GameProperty,QString)));
    connect(gameFileData.unitProperties, SIGNAL(propertyUpdated(QString,GameProperty,QString)),
            unitWidget, SLOT(updateUnitProperty(QString,GameProperty,QString)));
    connect(gameFileData.unitProperties, SIGNAL(propertyRemoved(QString)),
            unitWidget, SLOT(removeUnitProperty(QString)));*/

    // END FIX

    /*connect(gameFileData.columns, SIGNAL(columnAdded(Column,QString)),
            optionWidget, SLOT(addColumn(Column,QString)));
    connect(gameFileData.columns, SIGNAL(columnUpdated(QString,Column,QString)),
            optionWidget, SLOT(updateColumn(QString,Column,QString)));
    connect(gameFileData.columns, SIGNAL(columnRemoved(QString)), optionWidget,
            SLOT(removeColumn(QString)));*/

    /*connect(gameFileData.columns, SIGNAL(columnAdded(Column,QString)),
            itemWidget, SLOT(addColumn(Column,QString)));
    connect(gameFileData.columns, SIGNAL(columnUpdated(QString,Column,QString)),
            itemWidget, SLOT(updateColumn(QString,Column,QString)));
    connect(gameFileData.columns, SIGNAL(columnRemoved(QString)), itemWidget,
            SLOT(removeColumn(QString)));*/

    // \FIXME: Commented..

    /*connect(gameFileData.columns, SIGNAL(columnAdded(Column,QString)),
            unitWidget, SLOT(addColumn(Column,QString)));
    connect(gameFileData.columns, SIGNAL(columnUpdated(QString,Column,QString)),
            unitWidget, SLOT(updateColumn(QString,Column,QString)));
    connect(gameFileData.columns, SIGNAL(columnRemoved(QString)), unitWidget,
            SLOT(removeColumn(QString)));

    connect(gameFileData.columns, SIGNAL(cleared()), unitWidget, SLOT(clearAllColumns()));
    connect(&unitCategories, SIGNAL(cleared()), unitWidget, SLOT(clearAllCategories()));
    connect(gameFileData.unitProperties, SIGNAL(cleared()), unitWidget, SLOT(clearAllProperties()));*/

    // Set up "modified()" signal

    connect(&armyData.unitCategories, SIGNAL(modified()), this, SLOT(setUnsaved()));
    connect(&armyData.itemCategories, SIGNAL(modified()), this, SLOT(setUnsaved()));
    connect(&armyData.optionCategories, SIGNAL(modified()), this, SLOT(setUnsaved()));
    connect(&armyData.globalTexts, SIGNAL(modified()), this, SLOT(setUnsaved()));
    connect(&armyData.items, SIGNAL(modified()), this, SLOT(setUnsaved()));
    connect(&armyData.options, SIGNAL(modified()), this, SLOT(setUnsaved()));
    connect(&armyData.units, SIGNAL(modified()), this, SLOT(setUnsaved()));

    connect(ui->infArmyName, SIGNAL(textEdited(QString)), this, SLOT(setUnsaved()));
    connect(ui->infComments, SIGNAL(textChanged()), this, SLOT(setUnsaved()));
    connect(ui->infCreator, SIGNAL(textEdited(QString)), this, SLOT(setUnsaved()));
    connect(ui->infVersion, SIGNAL(textEdited(QString)), this, SLOT(setUnsaved()));
    connect(ui->infWeb, SIGNAL(textEdited(QString)), this, SLOT(setUnsaved()));


    isSaved = true;

    // Language files. Based on http://developer.qt.nokia.com/wiki/How_to_create_a_multi_language_application

    // - Create the languages menu with the default language (English)
    languageGroup = new QActionGroup(ui->menuLanguage);
    QAction *defaultLang = new QAction("English", languageGroup);
    defaultLang->setCheckable(true);
    defaultLang->setChecked(true);
    defaultLang->setData(QVariant("en"));
    ui->menuLanguage->addAction(defaultLang);

    // - Look for language  files located in "languages" directory (if it does not exist, will search in the application directory)

    QDir dir(QApplication::applicationDirPath());
    dir.cd("languages");

    // - Language files should be named armyeditor_language.qm (ISO 639-1 Code)

    QStringList languageFiles = dir.entryList(QStringList("armyeditor_*.qm"));
    QString systemLanguage = QLocale::system().name();

    for (int i = 0; i < languageFiles.size(); ++i) {

            QString locale = languageFiles.at(i);
            locale.truncate(locale.lastIndexOf('.'));
            locale.remove(0, locale.indexOf('_') + 1);

            QString lang = QLocale::languageToString(QLocale(locale).language());

            QAction *action = new QAction(lang, languageGroup);
            action->setCheckable(true);
            action->setData(locale);

            ui->menuLanguage->addAction(action);

            // - Load the system language if available
            if(systemLanguage.contains(locale)) {
                loadLanguage(locale);
                action->setChecked(true);
            }
    }

    // - Set up triggered signal

    connect(languageGroup, SIGNAL(triggered(QAction *)), this, SLOT(languageChanged(QAction *)));

    // Initialize when the event loop starts

    QTimer::singleShot(0, this, SLOT(initialize()));
}

ArmyEditor::~ArmyEditor()
{
    delete ui;
}

void ArmyEditor::initialize() {
    // This function makes sure an Army File is opened/created before we can work with the MainWindow

    StartDialog dialog;
    QFileDialog fileDialog(0, tr("Select Game File"), qApp->applicationDirPath(), tr("yALB Game File (*.ygf)"));
    fileDialog.setFileMode(QFileDialog::ExistingFile);
    while(1) {
        if(dialog.exec() == StartDialog::Accepted) {
            if(dialog.getResult() == StartDialog::CreateFile) {
                if(fileDialog.exec() == QFileDialog::Accepted) {
                    QString gameFile = fileDialog.selectedFiles().at(0);
                    if(gameFile.isEmpty() == false && newArmyFile(gameFile)) {
                        break;
                        //return true;
                    }
                }
            } else {
                if(fileDialog.exec() == QFileDialog::Accepted) {
                    QString gameFile = fileDialog.selectedFiles().at(0);
                    fileDialog.setFilter(tr("yALB Army File (*.yaf)"));
                    if(gameFile.isEmpty() == false && fileDialog.exec() == QFileDialog::Accepted) {
                        QString armyFile = fileDialog.selectedFiles().at(0);
                        if(armyFile.isEmpty() == false && openArmyFile(armyFile, gameFile)) {
                            break;
                            //return true;
                        } else
                            fileDialog.setFilter(tr("yALB Game File (*.ygf)"));
                    }
                }
            }
        } else {
            // User exited from Start Dialog, finish app
            this->close();
            //return false;
            break;
        }
    }
}

void ArmyEditor::loadLanguage(QString language) {
    qApp->removeTranslator(&qtTranslator);
    qApp->removeTranslator(&editorTranslator);

    if(!language.isEmpty()) {
        qtTranslator.load("qt_" + language,
                          QLibraryInfo::location(QLibraryInfo::TranslationsPath));
        qApp->installTranslator(&qtTranslator);
        editorTranslator.load("armyeditor_" + language, QApplication::applicationDirPath() + "/languages");
        qApp->installTranslator(&editorTranslator);
        currentLanguage = language;
    }
}

void ArmyEditor::languageChanged(QAction *action) {
    if(action) {
        QString newLanguage = action->data().toString();
        if(currentLanguage != newLanguage)
            loadLanguage(newLanguage);
    }
}


void ArmyEditor::clearInheritanceForm() {
    // Items...
    ui->inhItemCost->setValue(0);
    ui->inhMaxNumber->setValue(0);

    // Categories...
    ui->inhNumericLimit->setValue(0);
    ui->inhPercentageLimit->setValue(0);
    ui->inhPointsLimit->setValue(0);

    // Options...
    ui->inhOptionCost->setValue(0);
}

void ArmyEditor::resetInheritanceForm() {
    clearInheritanceForm();

    // Collections..
    inheritedUnitCategoryData.clear();
    inheritedItemCategoryData.clear();
    inheritedOptionCategoryData.clear();
    inheritedItemData.clear();
    inheritedOptionData.clear();
}

void ArmyEditor::setSaved(bool saved) {
    if(isSaved != saved) {
        isSaved = saved;
        ui->actionSaveArmyFile->setEnabled(!saved);
    }
}

bool ArmyEditor::unsavedFileMessage() {
    // This function returns true if the application can proceed or returns false if it has to abort the operation
    if(!isSaved) {
        QMessageBox::StandardButton result = QMessageBox::warning(this, tr("Army File not saved"),
                                                                  tr("The current army is not saved. Would you like to save it before proceeding?"),
                                                                  QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Yes);
        if(result == QMessageBox::Yes) {
            on_actionSaveArmyFile_triggered();
            return true;
        } else if(result == QMessageBox::Cancel)
            return false;
        else
            return true;
    } else
        return true;
}

bool ArmyEditor::newArmyFile(const QString &gameFilePath) {
    FileInformation gameInfo;
    setWidgetSignalsConnected(false);
    setInheritanceSignalsConnected(true);
    if(StructReader::readGameFile(gameData.toGameFileStructs(), gameInfo, gameFilePath, this) == StructReader::Success) {
        ui->loadedFile->setText(gameFilePath);
        ui->lgameName->setText(gameInfo.name);
        ui->lgameCreator->setText(gameInfo.creator);
        ui->lgameVersion->setText(gameInfo.version);
        ui->lgamePage->setText(gameInfo.website);
        ui->lgameComments->setText(gameInfo.comments);

        ui->infArmyName->setText("");
        ui->infCreator->setText("");
        ui->infVersion->setText("");
        ui->infWeb->setText("");
        ui->infComments->setPlainText("");

        clearAll();

        // \FIXME: Reset ALL!
        // Only need to reset units and globalTexts as other collections were reset with readGameFile()
        armyData.toArmyFileStructs().clearAll();

        resetInheritanceForm();

        setSaved(false);
        savedFile = "";

        setWidgetSignalsConnected(true);
        setInheritanceSignalsConnected(false);

        ui->statusBar->showMessage(tr("New army file started successfuly"), 10000);
        return true;
    } else {
        setWidgetSignalsConnected(true);
        setInheritanceSignalsConnected(false);

        ui->statusBar->showMessage(tr("There was a problem while loading game file. Previous data was not deleted"), 10000);
        return false;
    }
}

bool ArmyEditor::openArmyFile(const QString &armyFilePath, const QString &gameFilePath) {
    if(newArmyFile(gameFilePath)) {
        FileInformation armyInfo;
        ArmyFileStructs armyFileData = armyData.toArmyFileStructs();
        armyFileData.inheritedItemCategoryData = &inheritedItemCategoryData;
        armyFileData.inheritedUnitCategoryData = &inheritedUnitCategoryData;
        armyFileData.inheritedOptionCategoryData = &inheritedOptionCategoryData;

        armyFileData.inheritedItemData = &inheritedItemData;
        armyFileData.inheritedOptionData = &inheritedOptionData;

        if(StructReader::readArmyFile(armyFileData, armyInfo, armyFilePath, this,0, false) == StructReader::Success) {
            ui->infArmyName->setText(armyInfo.name);
            ui->infCreator->setText(armyInfo.creator);
            ui->infVersion->setText(armyInfo.version);
            ui->infWeb->setText(armyInfo.website);
            ui->infComments->setPlainText(armyInfo.comments);
            setSaved(true);
            savedFile = armyFilePath;
            ui->statusBar->showMessage(tr("File %1 opened successfully").arg(armyFilePath), 10000);
            return true;
        } else {
            setSaved(false);
            savedFile = "";
            ui->statusBar->showMessage(tr("There was a problem while loading army file %1").arg(armyFilePath), 10000);
            return false;
        }
    } else
        return false;
}

bool ArmyEditor::saveArmyFile(const QString &path) {
    QFile file(path);
    if(file.open(QFile::WriteOnly)) {

        QXmlStreamWriter writer(&file);
        StructWriter sw(writer);

        writer.writeStartDocument();
        writer.writeStartElement("yALBArmyEditor");
        writer.writeAttribute("version", "0.1");

        sw.writeFileInformation(FileInformation(ui->infArmyName->text(),
                                                ui->infCreator->text(),
                                                ui->infVersion->text(),
                                                ui->infWeb->text(),
                                                ui->infComments->toPlainText()));
        sw.writeInheritedUnitCategoryData(inheritedUnitCategoryData);
        sw.writeInheritedOptionCategoryData(inheritedOptionCategoryData);
        sw.writeInheritedItemCategoryData(inheritedItemCategoryData);
        sw.writeInheritedItemData(inheritedItemData);
        sw.writeInheritedOptionData(inheritedOptionData);

        // \FIXME: Commented.

        /*sw.writeUnitCategories(armyModels.unitCategoryModel->getOrderedPairs());
        sw.writeOptionCategories(armyModels.optionCategoryModel->getOrderedPairs());
        sw.writeItemCategories(armyModels.itemCategoryModel->getOrderedPairs());

        sw.writeOptions(optionWidget->getOrderedOptions());

        sw.writeItems(armyModels.itemModel->getOrderedPairs());
        sw.writeUnits(unitWidget->getOrderedUnits());
        sw.writeGlobalTexts(textWidget->getOrderedTexts());*/

        writer.writeEndDocument();
        file.close();
        setSaved(true);
        savedFile = path;
        ui->statusBar->showMessage(tr("File %1 saved successfully").arg(path), 10000);
        return true;
    } else
        return false;
}

void ArmyEditor::clearAll() {
    // Cleans all textboxes and other controls from all tabs
    unitCategoryWidget->clearCategoryForm();
    optionCategoryWidget->clearCategoryForm();
    itemCategoryWidget->clearCategoryForm();
    optionWidget->clearOptionForm();
    itemWidget->clearItemForm();
    unitWidget->clearUnitForm();
    textWidget->clearGlobalTextForm();
    clearInheritanceForm();
}

void ArmyEditor::on_actionNewArmyFile_triggered()
{
    if(unsavedFileMessage()) {
        QString gamePath = QFileDialog::getOpenFileName(this, tr("Select Game File"), QString(), tr("yALB Game File (*.ygf)"));
        if(!gamePath.isEmpty()) {
            // Start a new Army File
            newArmyFile(gamePath);
        }
    }
}


void ArmyEditor::on_actionOpenArmyFile_triggered()
{
    if (unsavedFileMessage()) {
        QString gamePath = QFileDialog::getOpenFileName(this, tr("Select Game File"), QString(), tr("yALB Game File (*.ygf)"));
        if(!gamePath.isEmpty()) {
            QString armyPath = QFileDialog::getOpenFileName(this, tr("Open Army File"), QString(), tr("yALB Army File (*.yaf)"));
            if(!armyPath.isEmpty())
                openArmyFile(armyPath, gamePath);
        }
    }
}

void ArmyEditor::on_actionSaveArmyFile_triggered()
{
    if(!savedFile.isEmpty())
        saveArmyFile(savedFile);
    else {
        on_actionSaveArmyFileAs_triggered();
    }
}

void ArmyEditor::on_actionSaveArmyFileAs_triggered()
{
    QString path = QFileDialog::getSaveFileName(this, tr("Save Army File"), QString(), tr("yALB Army File (*.yaf)"));
    if (!path.isEmpty())
        saveArmyFile(path);
}

void ArmyEditor::on_actionExit_triggered()
{
    this->close();
}

void ArmyEditor::on_inheritTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
    Q_UNUSED(previous)
    if(current && current->parent()) {
        QTreeWidgetItem *parentItem = current->parent();
        int hierarchyLevel = 1;

        // Let's find the top level item for current item. We reach the top level item when the parent is NULL

        while(parentItem->parent()) {
            parentItem = parentItem->parent();
            ++hierarchyLevel;
        }
        QString key = ui->inheritTree->currentItem()->data(0, Qt::UserRole).toString();
        int index = ui->inheritTree->indexOfTopLevelItem(parentItem);
        if(index >= 0 && index <= 2 && !key.isEmpty() && hierarchyLevel == 2) { // Is it category, item or option?
            ui->inheritSettings->setCurrentIndex(index + 1); // Set Stacked Widget to index + 1 because page 0 has no settings
            ui->inheritSaveButton->setEnabled(true);

            switch(index) {
            case 0: { // Category settings: Numeric Limit, Points Limit and Percentage Limit
                int categoryType = parentItem->indexOfChild(current->parent());
                switch(categoryType) {
                case 0: { // Unit category
                    const InheritedCategoryData &data = inheritedUnitCategoryData.value(key);

                    ui->inhNumericLimit->setValue(data.numericLimit);
                    ui->inhPointsLimit->setValue(data.pointLimit);
                    ui->inhPercentageLimit->setValue(data.percentageLimit);
                    break;
                }
                case 1: { // Option category
                    const InheritedCategoryData &data = inheritedOptionCategoryData.value(key);

                    ui->inhNumericLimit->setValue(data.numericLimit);
                    ui->inhPointsLimit->setValue(data.pointLimit);
                    ui->inhPercentageLimit->setValue(data.percentageLimit);
                    break;
                }
                case 2: { // Item category
                    const InheritedCategoryData &data = inheritedItemCategoryData.value(key);

                    ui->inhNumericLimit->setValue(data.numericLimit);
                    ui->inhPointsLimit->setValue(data.pointLimit);
                    ui->inhPercentageLimit->setValue(data.percentageLimit);
                    break;
                }
                default:
                    QMessageBox::critical(this, tr("Unexpected value"),
                                          tr("ArmyEditor got an unexpected value in method on_inheritTree_currentItemChanged(). Please report this in http://code.google.com/p/yalb"));
                }
                break;
            }
            case 1: { // Item settings: Default cost, Max number
                const InheritedItemData &data = inheritedItemData.value(key);

                ui->inhItemCost->setValue(data.cost);
                ui->inhMaxNumber->setValue(data.maxNumber);
                break;
            }
            case 2: // Option settings: Default cost
                ui->inhOptionCost->setValue(inheritedOptionData.value(key).cost);
                break;
            }
        }
        else { // There are no settings for selected row
            ui->inheritSettings->setCurrentIndex(0);
            ui->inheritSaveButton->setEnabled(false);
        }
    } else {
        ui->inheritSettings->setCurrentIndex(0);
        ui->inheritSaveButton->setEnabled(false);
    }
}

void ArmyEditor::on_inheritSaveButton_clicked()
{
    QString key = ui->inheritTree->currentItem()->data(0, Qt::UserRole).toString();
    switch(ui->inheritSettings->currentIndex()) {
    case 1: { // Category settings: Numeric Limit, Points Limit and Percentage Limit
        int categoryType = ui->inheritTree->topLevelItem(0)->indexOfChild(ui->inheritTree->currentItem()->parent());
        switch(categoryType) {
        case 0: { // Unit category
            inheritedUnitCategoryData[key].numericLimit = ui->inhNumericLimit->value();
            inheritedUnitCategoryData[key].pointLimit = ui->inhPointsLimit->value();
            inheritedUnitCategoryData[key].percentageLimit = ui->inhPercentageLimit->value();
            break;
        }
        case 1: { // Option category
            inheritedOptionCategoryData[key].numericLimit = ui->inhNumericLimit->value();
            inheritedOptionCategoryData[key].pointLimit = ui->inhPointsLimit->value();
            inheritedOptionCategoryData[key].percentageLimit = ui->inhPercentageLimit->value();
            break;
        }
        case 2: { // Item category
            inheritedItemCategoryData[key].numericLimit = ui->inhNumericLimit->value();
            inheritedItemCategoryData[key].pointLimit = ui->inhPointsLimit->value();
            inheritedItemCategoryData[key].percentageLimit = ui->inhPercentageLimit->value();
            break;
        }
        default:
            QMessageBox::critical(this, tr("Unexpected value"),
                                  tr("ArmyEditor got an unexpected value in method on_inheritSaveButton_clicked(). Please report this in http://code.google.com/p/yalb"));

        }
        break;
    }
    case 2: { // Item settings: Default cost, Max number
        inheritedItemData[key].cost = ui->inhItemCost->value();
        inheritedItemData[key].maxNumber = ui->inhMaxNumber->value();
        break;
    }
    case 3: // Option settings: Default cost
        inheritedOptionData[key].cost = ui->inhOptionCost->value();
        break;
    }
}

void ArmyEditor::addUnitCategory(const GameCategory &category, const QString &key) {
    addInheritanceItem(category.getName(), key, ui->inheritTree->topLevelItem(0)->child(0));
}

void ArmyEditor::clearUnitCategories() {
    qDeleteAll(ui->inheritTree->topLevelItem(0)->child(0)->takeChildren());
}

void ArmyEditor::addOptionCategory(const GameCategory &category, const QString &key) {
    addInheritanceItem(category.getName(), key, ui->inheritTree->topLevelItem(0)->child(1));
    addInheritanceItem(category.getName(), key, ui->inheritTree->topLevelItem(2));
}

void ArmyEditor::clearOptionCategories() {
    qDeleteAll(ui->inheritTree->topLevelItem(0)->child(1)->takeChildren());

    QTreeWidgetItem *treeItem = ui->inheritTree->topLevelItem(2);

    qDeleteAll(treeItem->child(0)->takeChildren());

    for(int i = treeItem->childCount()-1; i>=1; --i) {
        delete treeItem->child(i);
    }
}

void ArmyEditor::addItemCategory(const GameCategory &category, const QString &key) {
    addInheritanceItem(category.getName(), key, ui->inheritTree->topLevelItem(0)->child(2));
    addInheritanceItem(category.getName(), key, ui->inheritTree->topLevelItem(1));
}

void ArmyEditor::clearItemCategories() {
    qDeleteAll(ui->inheritTree->topLevelItem(0)->child(2)->takeChildren());

    QTreeWidgetItem *treeItem = ui->inheritTree->topLevelItem(1);

    qDeleteAll(treeItem->child(0)->takeChildren());

    for(int i = treeItem->childCount()-1; i>=1; --i) {
        delete treeItem->child(i);
    }
}

void ArmyEditor::addItem(const GameItem& item, const QString &key) {
    QTreeWidgetItem *treeItem = ui->inheritTree->topLevelItem(1);
    int index = 0; // Default to "No category"
    if(!item.category.isEmpty()) {
        for(int i = 0; i<treeItem->childCount(); ++i) {
            if(treeItem->child(i)->data(0, Qt::UserRole).toString() == item.category) {
                index = i;
                break;
            }
        }
    }
    addInheritanceItem(item.getName(), key, treeItem->child(index));
}

void ArmyEditor::addOption(const UnitOption& option, const QString &key) {
    QTreeWidgetItem *treeItem = ui->inheritTree->topLevelItem(2);
    int index = 0; // Default to "No category"
    if(!option.category.isEmpty()) {
        for(int i = 0; i<treeItem->childCount(); ++i) {
            if(treeItem->child(i)->data(0, Qt::UserRole).toString() == option.category) {
                index = i;
                break;
            }
        }
    }
    addInheritanceItem(option.getName(), key, treeItem->child(index));
}



void ArmyEditor::setWidgetSignalsConnected(bool value) {
     // \FIXME: Delete when it is not used anymore
    /*unitCategoryWidget->setSignalsConnected(value);
    itemCategoryWidget->setSignalsConnected(value);
    optionCategoryWidget->setSignalsConnected(value);*/
    //itemWidget->setSignalsConnected(value);
    //optionWidget->setSignalsConnected(value);
}

void ArmyEditor::setInheritanceSignalsConnected(bool value) {

    // \FIXME: Commented.
    /*if(value) {
        connect(&optionCategories, SIGNAL(categoryAdded(GameCategory,QString)),
                this, SLOT(addOptionCategory(GameCategory,QString)));
        connect(&optionCategories, SIGNAL(cleared()),
                this, SLOT(clearOptionCategories()));

        connect(&unitCategories, SIGNAL(categoryAdded(GameCategory,QString)),
                this, SLOT(addUnitCategory(GameCategory,QString)));
        connect(&unitCategories, SIGNAL(cleared()),
                this, SLOT(clearUnitCategories()));

        connect(&itemCategories, SIGNAL(categoryAdded(GameCategory,QString)),
                this, SLOT(addItemCategory(GameCategory,QString)));
        connect(&itemCategories, SIGNAL(cleared()),
                this, SLOT(clearItemCategories()));

        connect(&options, SIGNAL(optionAdded(UnitOption,QString)),
                this, SLOT(addOption(UnitOption,QString)));

        connect(&items, SIGNAL(itemAdded(GameItem,QString)),
                this, SLOT(addItem(GameItem,QString)));
    } else {
        disconnect(&optionCategories, SIGNAL(categoryAdded(GameCategory,QString)),
                this, SLOT(addOptionCategory(GameCategory,QString)));
        disconnect(&optionCategories, SIGNAL(cleared()),
                this, SLOT(clearOptionCategories()));

        disconnect(&unitCategories, SIGNAL(categoryAdded(GameCategory,QString)),
                this, SLOT(addUnitCategory(GameCategory,QString)));
        disconnect(&unitCategories, SIGNAL(cleared()),
                this, SLOT(clearUnitCategories()));

        disconnect(&itemCategories, SIGNAL(categoryAdded(GameCategory,QString)),
                this, SLOT(addItemCategory(GameCategory,QString)));
        disconnect(&itemCategories, SIGNAL(cleared()),
                this, SLOT(clearItemCategories()));

        disconnect(&options, SIGNAL(optionAdded(UnitOption,QString)),
                this, SLOT(addOption(UnitOption,QString)));

        disconnect(&items, SIGNAL(itemAdded(GameItem,QString)),
                this, SLOT(addItem(GameItem,QString)));
    }*/
}

void ArmyEditor::addInheritanceItem(const QString& name, const QString &key, QTreeWidgetItem *parent) {
    QTreeWidgetItem *item = new QTreeWidgetItem(QStringList(name));
    item->setData(0, Qt::UserRole, QVariant(key));
    parent->addChild(item);
}

void ArmyEditor::removeInheritanceItem(const QString& key, QTreeWidgetItem *parent) {
    for(int i = 0; i<parent->childCount(); ++i) {
        if(parent->child(i)->data(0, Qt::UserRole).toString() == key) {
            delete parent->child(i);
        }
    }
}

void ArmyEditor::closeEvent(QCloseEvent *event) {
    if (unsavedFileMessage())
        event->accept();
    else
        event->ignore();
}

void ArmyEditor::changeEvent(QEvent *event) {
    if(event->type() == QEvent::LanguageChange)
        ui->retranslateUi(this);
    QMainWindow::changeEvent(event);
}
